package com.xyh.transaction.config;

import com.xyh.transaction.filter.JwtAuthenticationTokenFilter;
import com.xyh.transaction.handler.AccessDeniedHandlerImpl;
import com.xyh.transaction.handler.AuthenticationEntryPointImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private IgnoreUrlsConfig ignoreUrlsConfig;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Autowired
    private AuthenticationEntryPointImpl authenticationEntryPoint;

    @Autowired
    private AccessDeniedHandlerImpl accessDeniedHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                .csrf().disable()//关闭csrf
                //不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                // 对于登录注册接口允许匿名访问
                .antMatchers(ignoreUrlsConfig.getAnonymous().toArray(new String[0])).anonymous()
//                // 放行swagger
//                .antMatchers(
//                        "/swagger-ui.html",
//                        "/swagger-ui/*",
//                        "/swagger-resources/**",
//                        "/v2/api-docs",
//                        "/v3/api-docs",
//                        "/webjars/**",
//                        "/configuration/ui").permitAll()
//                // 允许未登录访问home，goods，category接口数据，可以细分到获取数据接口，目前先前全部放行
//                .antMatchers(
//                        "/category/**",
//                        "/goods/**",
//                        "/home/**").permitAll()
////                .antMatchers("/category/list").hasAuthority("Execute")// 基于配置的权限控制
//                // 支付接口
//                .antMatchers(
//                        "/pay/**").permitAll()
//                // 上传图片
//                .antMatchers(
//                        "/file/upload/img",
//                        "/file/download/img/*").permitAll()
//                // websocket
////                .antMatchers("/socket/**").permitAll()
//                //websocket
//                .antMatchers("/ws/**").permitAll()
                .antMatchers(ignoreUrlsConfig.getPermitAll().toArray(new String[0])).permitAll()
                .antMatchers(ignoreUrlsConfig.getSpecial().toArray(new String[0])).permitAll()
                // 除上面外的所以请求全部需要鉴权
                .anyRequest().authenticated();

        http
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

        // 允许跨域
        http.cors().configurationSource(corsConfigurationSource());

    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedHeader("*");
//        corsConfiguration.addAllowedOrigin("*");
        // 本地地址
        corsConfiguration.addAllowedOrigin("http://localhost:8848");
        corsConfiguration.addAllowedOrigin("http://localhost:5173");
        // 线上地址（华为云）
        corsConfiguration.addAllowedOrigin("http://123.60.16.38:81");
        corsConfiguration.addAllowedOrigin("http://123.60.16.38:82");
        // 线上地址（腾讯云）
        corsConfiguration.addAllowedOrigin("http://124.223.56.87:81");
        corsConfiguration.addAllowedOrigin("http://124.223.56.87:82");
//        corsConfiguration.addAllowedOrigin("https://7999-220-248-18-54.ngrok-free.app");
        corsConfiguration.addAllowedOrigin("https://quick-dane-honestly.ngrok-free.app");
        // aws
        corsConfiguration.addAllowedOrigin("https://xiaoyihao.tech");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.setAllowCredentials(true); // 允许使用凭证
        // 允许的预检请求方法
        corsConfiguration.addAllowedMethod(HttpMethod.OPTIONS);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",corsConfiguration);
        return source;
    }
}
